/*
 * osc.c
 *
 *  Created on: Aug 1, 2013
 *      Author: Ken Arok
 *
 *      Revision history:
 *      ---------------------------------------------------------
 *      Date			|	Revised by		|	Description
 *      ---------------------------------------------------------
 *      1. Aug 1, 2013	|	Yosef			| New establishment
 *
 *
 * \file
 *
 * \brief Hardware Abstraction Layer of Oscillator Management UC3C0512C
 *
 * Copyright (c) 2013 PT Hanindo Automation Solutions. All rights reserved.
 *
 */

#include "config_board.h"

#if BOARD_1_0_USED

#include <osc.h>

#ifdef BOARD_OSC0_HZ
void osc_priv_enable_osc0(void)
{
	irqflags_t flags;

	flags = cpu_irq_save();
	AVR32_SCIF.unlock = 0xaa000000 | AVR32_SCIF_OSCCTRL;
	AVR32_SCIF.oscctrl[0] = (OSC0_STARTUP_VALUE << AVR32_SCIF_OSCCTRL_STARTUP)
			| (OSC0_GAIN_VALUE << AVR32_SCIF_OSCCTRL_GAIN)
			| (OSC0_MODE_VALUE << AVR32_SCIF_OSCCTRL_MODE)
			| (1U << AVR32_SCIF_OSCCTRL_OSCEN);
	cpu_irq_restore(flags);
}

void osc_priv_disable_osc0(void)
{
	irqflags_t flags;

	flags = cpu_irq_save();
	AVR32_SCIF.unlock = 0xaa000000 | AVR32_SCIF_OSCCTRL;
	AVR32_SCIF.oscctrl[0] = 0;
	cpu_irq_restore(flags);
}
#endif /* BOARD_OSC0_HZ */


void osc_priv_enable_rc8m(void)
{
	irqflags_t flags;
	uint32_t   rccr8;
    uint32_t* calibration_bits = (uint32_t *)0x80800200;
	/* Wait for the CALIB field to be updated from fuses after reset */
	while (!(AVR32_SCIF.rccr8 & AVR32_SCIF_RCCR8_FCD_MASK)) {
		/* Do nothing */
	}

	/* Enable the oscillator without touching the CALIB and FCD fields */
	flags = cpu_irq_save();
	rccr8 = AVR32_SCIF.rccr8;
	rccr8 &= AVR32_SCIF_RCCR8_FCD_MASK | ((*calibration_bits)&AVR32_SCIF_RCCR8_CALIB_MASK);
	rccr8 |= 1U << AVR32_SCIF_RCOSC8_EN;
	AVR32_SCIF.unlock = 0xaa000000 | AVR32_SCIF_RCCR8;
	AVR32_SCIF.rccr8 = rccr8;
	cpu_irq_restore(flags);
}

void osc_priv_disable_rc8m(void)
{
	irqflags_t flags;
	uint32_t   rccr8;

	/* Disable the oscillator without touching the CALIB and FCD fields */
	flags = cpu_irq_save();
	rccr8 = AVR32_SCIF.rccr8;
	rccr8 &= AVR32_SCIF_RCCR8_FCD_MASK | AVR32_SCIF_RCCR8_CALIB_MASK;
	AVR32_SCIF.unlock = 0xaa000000 | AVR32_SCIF_RCCR8;
	AVR32_SCIF.rccr8 = rccr8;
	cpu_irq_restore(flags);
}

void osc_priv_enable_rc120m(void)
{
	irqflags_t flags;

	flags = cpu_irq_save();
	AVR32_SCIF.unlock = 0xaa000000 | AVR32_SCIF_RC120MCR;
	AVR32_SCIF.rc120mcr = 1U << AVR32_SCIF_RC120MCR_EN;
	cpu_irq_restore(flags);
}

void osc_priv_disable_rc120m(void)
{
	irqflags_t flags;

	flags = cpu_irq_save();
	AVR32_SCIF.unlock = 0xaa000000 | AVR32_SCIF_RC120MCR;
	AVR32_SCIF.rc120mcr = 0;
	cpu_irq_restore(flags);
}

#endif /* BOARD_1_0_USED */

